#pragma once

#include <stdint.h>

#include <butil/time.h>
#include <glog/logging.h>

#include "doc/normal_document.h"
#include "doc/index_doc_field_convertor.h"

namespace hawking {
namespace indexlib {

class DocumentCreator {
public:
    DocumentCreator(std::shared_ptr<IndexlibIndexConfig> index_config) :
        index_config_(index_config), pk_field_name_(index_config.pk_field_name()) {
        convertor_ = std::make_unique<IndexDocFieldConvertor>(index_config_);
        for (size_t idx = 0; idx < index_config_->fields_size(); ++idx) {
            const std::string& field_name = index_config_->fields(idx).field_name();
            field_name2id_.emplace(field_name, idx);
        }
    }
    ~DocumentCreator() = default;

    std::shared_ptr<NormalDocument> CreateNormalDocument(
        const indexlib::IndexlibMessage& item) const;

    bool SetPrimaryKey(
        const indexlib::IndexlibMessage& item,
        std::shared_ptr<NormalDocument> doc) const;

    bool SetDocumentValue(
        const indexlib::IndexlibMessage& item,
        std::shared_ptr<NormalDocument> doc) const;

    static int64_t DeadTime(int64_t life_cycle) {
        return butil::gettimeofday_s() + life_cycle;
    }

    bool FieldName2Id(const std::string& field_name, int32_t* field_id) const {
        auto iter = field_name2id_.find(field_name);
        if (iter == field_name2id_.end()) {
            return false;
        }

        *field_id = iter->second;
        return true;
    }

    bool FieldName2IdAndType(
        const std::string& field_name,
        int32_t* field_id,
        util::ColumnType* field_type) const  {
        auto iter = field_name2id_.find(field_name);
        if (iter == field_name2id_.end()) {
            return false;
        }

        *field_id = iter->second;
        *field_type = index_config_->fields(*field_id).field_type();
        return true;
    }

private:
    bool IsIndex_(int32_t field_id) const;
    bool FetchPK_(const indexlib::IndexlibMessage& item, uint64_t* pk) const;

    std::shared_ptr<IndexlibIndexConfig> index_config_;
    std::unique_ptr<IndexDocFieldConvertor> convertor_;
    std::unordered_map<std::string, int32_t> field_name2id_;
    std::string pk_field_name_;
};

}
}